package utils.binary.impl;

import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import utils.binary.BytesSlices;
import utils.binary.io.BytesInputStream;
import utils.io.NumberMask;

/**
 * @author Zhou Yifan
 */
public class SingleBytesSliceArray extends BytesSlice implements BytesSlices {

    private int totalSize;

    /**
     * 构造函数
     *
     * @param dataBytes  数据字节数组
     * @param totalSize  总大小
     * @param dataOffset 起始位置
     * @param dataSize   单个数据大小
     */
    private SingleBytesSliceArray(byte[] dataBytes, int totalSize, int dataOffset, int dataSize) {
        super(dataBytes, dataOffset, dataSize);
        this.totalSize = totalSize;
    }

    /**
     * 总的字节数；包含各个子数据片段之间间隔的头部字节
     *
     * @return int
     */
    @Override
    public int getTotalSize() {
        return totalSize;
    }

    /**
     * 包含的子片段的数量
     *
     * @return int
     */
    @Override
    public int getCount() {
        return 1;
    }

    /**
     * 返回一个子数据片段
     *
     * @param idx 子数据片段的编号；大于等于 0 ，小于总数 {@link #getCount()}
     * @return {@link BytesSlice}
     */
    @Override
    public BytesSlice getDataSlice(int idx) {
        if (idx != 0) {
            throw new IllegalStateException("The specified idx is out of bound!");
        }
        return this;
    }

    @Contract("_ -> new")
    public static @NotNull SingleBytesSliceArray resolveDynamic(@NotNull BytesInputStream bytesStream) {
        int position  = bytesStream.getPosition();
        int size = (int) NumberMask.NORMAL.resolveMaskedNumber(bytesStream);
        int dataOffset = bytesStream.getPosition();
        bytesStream.skip(size);
        int totalSize = bytesStream.getPosition() - position;
        return new SingleBytesSliceArray(bytesStream.getOriginBytes(), totalSize, dataOffset, size);
    }

    @Contract("_, _ -> new")
    public static @NotNull BytesSlices resolveNumber(@NotNull NumberMask numberMask, @NotNull BytesInputStream bytesStream) {
        int position  = bytesStream.getPosition();
        byte headByte = bytesStream.readByte();
        int size = numberMask.resolveMaskLength(headByte);
        bytesStream.skip(size - 1);
        int totalSize = bytesStream.getPosition() - position;
        return new SingleBytesSliceArray(bytesStream.getOriginBytes(), totalSize, position, size);
    }

    @Contract("_, _ -> new")
    public static @NotNull SingleBytesSliceArray create(@NotNull BytesInputStream bytesStream, int itemSize) {
        int offset = bytesStream.getPosition();
        bytesStream.skip(itemSize);
        return new SingleBytesSliceArray(bytesStream.getOriginBytes(), itemSize, offset, itemSize);
    }

    @Contract("_, _, _ -> new")
    public static @NotNull SingleBytesSliceArray create(byte[] dataBytes, int offset, int size) {
        return new SingleBytesSliceArray(dataBytes, size, offset, size);
    }
}
